home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
msdos
/
viewers
/
msgifscn
/
gifscn.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-17
|
17KB
|
629 lines
/* GIFSCAN - scans through a GIF file and reports all parameters */
#ifndef lint
static char *SCCSid = "@(#)gifscn.c v1.2 changed 5/16/91 13:35:03";
#endif
#include <stdio.h>
#include <stdlib.h>
/* global values */
int Quiet = 0; /* don't print detail */
int Debug = 0; /* print debug/trace info */
extern int optind, opterr;
extern char *optarg;
/************************************************************************/
/* COLORMAP - reads color information in from the GIF file and displays */
/* it in a user selected method. This display may be in : */
/* hexidecimal (default), percentage, or decimal. User */
/* selects output method by placing a switch (-d, -p, -h) */
/* between the program name and GIF filename at request time.*/
colormap(out, dev, times, file_byte_cnt)
FILE *dev;
int times;
int out;
int *file_byte_cnt;
#define DECIMAL 1
#define PERCENT 2
#define HEXIDEC 3
#define MAX 255
{
unsigned int red;
unsigned int green;
unsigned int blue;
int print_cnt;
int i;
/* Start of procedure */
if (!Quiet) {
if (out == DECIMAL)
printf ("\nColor definitions in decimal (index #, R, G, B)\n");
if (out == PERCENT)
printf ("\nColor definitions by percentage (index #, R, G, B)\n");
if (out == HEXIDEC)
printf ("\nColor definitions in hexidecimal (index #, R, G, B)\n");
}
/* read and print the color definitions */
print_cnt = 0;
for (i = 0; (i < times); i++)
{
red = getc(dev);
green = getc(dev);
blue = getc(dev);
*file_byte_cnt += 3;
if (!Quiet) switch (out)
{
case DECIMAL :
printf ("%3d - %3d %3d %3d ", i, red, green, blue);
break;
case PERCENT :
red = (red * 100) / MAX;
green = (green * 100) / MAX;
blue = (blue * 100) / MAX;
printf ("%3d - %3d %3d %3d ", i, red, green, blue);
break;
case HEXIDEC :
printf ("%3d - %2x %2x %2x ", i, red, green, blue);
break;
}
print_cnt++;
if (!Quiet && print_cnt == 4)
{
printf ("\n");
print_cnt = 0;
}
}
if (!Quiet && (times % 4) != 0)
printf ("\n");
}
/************************************************************************/
/* GETBYTES - routine to retrieve two bytes of information from the GIF */
/* file and then shift them into correct byte order. The */
/* information is stored in Least Significant Byte order. */
unsigned int getbytes(dev, file_byte_cnt)
FILE *dev;
int *file_byte_cnt;
{
int byte1;
int byte2;
int result;
/* read bytes and shift over */
byte1 = getc(dev);
byte2 = getc(dev);
*file_byte_cnt += 2;
result = (byte2 << 8) | byte1;
return result;
}
/***********************************************************************/
/* IMAGEINF - routine to read the GIF image information and display it */
/* to the user's screen in an orderly fasion. If there are */
/* multiple images then IMAGEINF will be called to display */
/* multiple screens. */
imageinf(dev, bits_to_use, color_style, file_byte_cnt)
FILE *dev;
int bits_to_use;
int color_style;
int *file_byte_cnt;
{
int byte1;
int byte2;
int byte3;
int image_left;
int image_top;
int data_byte_cnt;
int bits_per_pix;
int color_res;
int colors;
int i;
int local;
int unexpected;
unsigned int width;
unsigned int height;
unsigned long bytetot;
unsigned long possbytes;
/* determine the image left value */
image_left = getbytes(dev, file_byte_cnt);
/* determine the image top value */
image_top = getbytes(dev, file_byte_cnt);
printf ("\nImage Left: %5d\t\tImage Top: %5d", image_left,
image_top);
/* determine the image width */
width = getbytes(dev, file_byte_cnt);
/* determine the image height */
height = getbytes(dev, file_byte_cnt);
printf ("\nImage Width: %5d\t\tImage Height: %5d", width, height);
/* check for interlaced image */
byte1 = getc(dev);
(*file_byte_cnt)++;
byte2 = byte1 & 0x40;
if (byte2 == 0x40)
printf ("\nInterlaced: Yes");
else
printf ("\nInterlaced: No");
/* check for a local map */
byte2 = byte1 & 0x80;
if (byte2 == 0x80)
{
local = 1;
printf ("\nLocal Color Map: Yes");
}
else
{
local = 0;
printf ("\nLocal Color Map: No");
}
/* check for the 3 zero bits */
byte2 = byte1 & 0x38;
if (byte2 != 0)
printf ("\n? -- Reserved zero bits in image not zeros.\n");
/* determine the # of color bits in local map */
bits_per_pix = byte1 & 0x07;
bits_per_pix++;
colors = 1 << bits_per_pix;
if (local == 1)
{
bits_to_use = bits_per_pix;
printf ("\nBits per pixel: %5d\t\t# colors : %5d", bits_per_pix,
colors);
colormap (color_style, dev, colors, file_byte_cnt);
}
/* retrieve the code size */
byte1 = getc(dev);
(*file_byte_cnt)++;
if ((byte1 < 2) || (byte1 > 8))
{
printf ("\n? -- Code size %d at start of image");
printf ("\n is out of range (2-8).\n");
}
else
printf ("\nLZW min code size (bits): %3d", byte1);
/* tally up the total bytes and read past each data block */
bytetot = 0;
possbytes = 0;
while ((data_byte_cnt = getc(dev)) > 0)
{
(*file_byte_cnt)++;
bytetot = bytetot + data_byte_cnt;
if (!Quiet) printf("\n Record size %d",data_byte_cnt);
for (i = 0; (i < data_byte_cnt); i++)
{
byte2 = getc(dev);
(*file_byte_cnt)++;
if (byte2 == EOF)
{
(*file_byte_cnt)--;
printf ("\n? -- EOF reached inside image data block.\n");
printf ("\n Located %d bytes into file.",*file_byte_cnt);
exit (2);
}
}
}
(*file_byte_cnt)++;
possbytes = (unsigned long) width * height;
i = 8 / bits_to_use;
possbytes = possbytes / i;
printf ("\nTotal number of bytes in image: %ld out of possible %ld\n",
bytetot, possbytes);
if (data_byte_cnt == EOF)
{
(*file_byte_cnt)--;
printf ("\n? -- EOF reached before zero byte count");
printf ("\n of image was read.\n");
printf ("\n Located %d bytes into file.",*file_byte_cnt);
exit (3);
}
}
/************************************************************************/
/* EXTNINFO - routine to read the GIF file for extension data and */
/* display it to the screen in an orderly fasion. This */
/* extension information may be located before, between, or */
/* after any of the image data. */
extninfo(dev, file_byte_cnt)
FILE *dev;
int *file_byte_cnt;
{
int byte1;
int byte2;
int i;
int data_byte_cnt;
unsigned long bytetot;
/* retrieve the function code */
byte1 = getc(dev);
(*file_byte_cnt)++;
printf ("\nGIF extension code %d located at byte %d", byte1,
*file_byte_cnt);
/* tally up the total bytes and read past each data block */
bytetot = 0;
while ((data_byte_cnt = getc(dev)) > 0)
{
(*file_byte_cnt)++;
bytetot = bytetot + data_byte_cnt;
for (i = 0; (i < data_byte_cnt); i++)
{
byte2 = getc(dev);
(*file_byte_cnt)++;
if (byte2 == EOF)
{
(*file_byte_cnt)--;
printf ("\n? -- EOF was reached inside extension data block.\n");
printf ("\n Located %d bytes into file.",*file_byte_cnt);
exit (2);
}
}
}
(*file_byte_cnt)++;
printf ("\nTotal number of bytes in extension: %ld\n", bytetot);
if (data_byte_cnt == EOF)
{
(*file_byte_cnt)--;
printf ("\n? -- EOF was reached before zero byte count");
printf ("\n of extension was read.\n");
printf ("\n Located %d bytes into file.",*file_byte_cnt);
exit (3);
}
}
/************************************************************************/
/* CHKUNEXP - routine to check for any unexpected nonzero data found */
/* within the GIF file. This routine will help determine */
/* where the unexpected data may reside in the file. */
chkunexp (unexpected, determiner)
int *unexpected;
int determiner;
{
/* Determine place in the GIF file */
if (determiner > 0)
{
printf ("\n? -- %d bytes of unexpected data found before",
*unexpected);
printf ("\n image %d.\n", determiner);
}
else if (determiner == -1)
{
printf ("\n? -- %d bytes of unexpected data found before",
*unexpected);
printf ("\n GIF file terminator.\n");
}
else if (determiner == -2)
{
printf ("\n? -- %d bytes of unexpected data found after",
*unexpected);
printf ("\n GIF file terminator.\n");
}
else
{
printf ("\n? -- %d bytes of unexpected data found at",
*unexpected);
printf ("\n or after expected GIF terminator byte.\n");
}
/* Zero out the unexpected variable for */
/* the next group that may be encountered */
*unexpected = 0;
}
/************************************************************************/
/* MAIN - the main routine reads the GIF file for the global GIF */
/* information which it displays to the user's screen. This */
/* routine also determines which subroutine to call and which */
/* information to process. */
main(argc, argv)
char *argv[];
int argc;
#define DECIMAL 1
#define PERCENT 2
#define HEXIDEC 3
{
char filename[15];
char version[7];
char style[5];
int byte1;
int byte2;
int byte3;
int image_left;
int image_top;
int data_byte_cnt;
int image_cnt;
int bits_per_pix;
int bits_to_use;
int color_res;
int colors;
int i;
int globl;
int end_gif_fnd;
int unexpected;
int color_style;
int switch_present;
int file_byte_cnt;
unsigned int width;
unsigned int height;
FILE *in;
/* Start of Processing */
/* If just one argument then display the message */
if (argc == 1)
{
printf ("\nUSAGE: gifscan color_opt filename\n");
printf ("\ncolor_opt specifies how color lookup table");
printf ("\n definitions are displayed");
printf ("\n -h : output as hexidecimal (0 - FF) (default)");
printf ("\n -d : output as decimal (0 - 255)");
printf ("\n -p : output as percentage (0 - 100)\n");
exit (0);
}
color_style = 0;
switch_present = 0;
while ((i = getopt(argc, argv, "dhpqD")) != EOF) {
switch (i) {
case 'd': /* decimal */
color_style = DECIMAL;
break;
case 'p': /* percent */
color_style = PERCENT;
break;
case 'h': /* hexadecimal */
color_style = HEXIDEC;
break;
case 'q': /* set quiet flag */
Quiet = 1;
break;
case 'D': /* debug (undoc) */
Debug = 1;
break;
default:
exit(1);
}
}
/* Check for GIF filename */
if (argc == optind) {
fprintf(stderr, "Missing filename(s)\nType gifscn for help\n");
exit(1);
}
else {
if (Debug) fprintf(stderr, "Filename: %s\n", argv[optind]);
/* copy the filename and open it */
strcpy(filename, argv[optind]);
in = fopen(filename, "rb");
if (in == NULL) {
fprintf(stderr, "Can't open file %s\n", filename);
exit(1);
}
}
image_cnt = 0;
end_gif_fnd = 0;
unexpected = 0;
file_byte_cnt = 0;
/* get version from file */
if ((version[0] = getc(in)) == 0x47)
{
for (i = 1; (i < 6); i++)
version[i] = getc(in);
version[6] = '\0';
printf ("\nVersion: %s", version);
}
else
{
printf ("\n? -- NOT a GIF file\n");
exit(1);
}
file_byte_cnt += 6;
/* determine screen width */
width = getbytes(in, &file_byte_cnt);
/* determine screen height */
height = getbytes(in, &file_byte_cnt);
printf ("\nScreen Width: %5d\tScreen Height: %5d", width,
height);
/* check for a Global Map */
byte1 = getc(in);
file_byte_cnt++;
byte2 = byte1 & 0x80;
if (byte2 == 0x80)
{
printf ("\nGlobal Color Map: Yes");
globl = 1;
}
else
{
printf ("\nGlobal Color Map: No");
globl = 0;
}
/* Check for the 0 bit */
byte2 = byte1 & 0x08;
if (byte2 != 0)
printf ("\n? -- Reserved zero bit is not zero.\n");
/* determine the color resolution */
byte2 = byte1 & 0x70;
color_res = byte2 >> 4;
/* get the background index */
byte3 = getc(in);
file_byte_cnt++;
printf ("\nColor resolution: %5d\tBackground index: %5d",
++color_res,
byte3);
/* determine the bits per pixel */
bits_per_pix = byte1 & 0x07;
bits_per_pix++;
bits_to_use = bits_per_pix;
/* determine # of colors in global map */
colors = 1 << bits_per_pix;
printf ("\nBits per pixel: %5d\t# colors: %5d\n", bits_per_pix,
colors);
/* check for the 0 byte */
byte1 = getc(in);
file_byte_cnt++;
if (byte1 != 0)
printf ("\n? -- Reserved byte after Background index is not zero.\n");
if (globl == 1)
colormap (color_style, in, colors, &file_byte_cnt);
/* check for the zero byte count, a new image, or */
/* the end marker for the gif file */
while ((byte1 = getc(in)) != EOF)
{
file_byte_cnt++;
if (byte1 == ',')
{
image_cnt++;
if (unexpected != 0)
chkunexp (&unexpected, image_cnt);
printf ("\nImage # %2d separator located at byte %d.",
image_cnt, file_byte_cnt);
imageinf (in, bits_to_use, color_style, &file_byte_cnt);
}
else if (byte1 == '!')
/* Extension data found */
extninfo (in, &file_byte_cnt);
else if (byte1 == ';')
/* GIF terminator located, check for any */
/* unexpected data found before terminator */
{
if (unexpected != 0)
chkunexp (&unexpected, -1);
end_gif_fnd = 1;
printf ("\nGIF terminator located at byte %d.\n",
file_byte_cnt);
}
else
unexpected++;
}
/* EOF has been reached - check last bytes read */
if (end_gif_fnd == 0)
{
printf ("\n? -- GIF file terminator ';' was not found.");
printf ("\n Expected at byte %d in file.\n",file_byte_cnt);
}
if ((unexpected != 0) && (end_gif_fnd == 0))
chkunexp (&unexpected, -3);
else if (unexpected != 0)
chkunexp (&unexpected, -2);
}